#include <stdio.h>
#include "types.h"
#include "rsa.h"
#include "random.h"
#include "hash.h"

#define HEAP_HINT NULL

/* import RSA public key elements (n, e) into RsaKey structure (key) */
int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e,
                             word32 eSz, RsaKey* key)
{
    if (n == NULL || e == NULL || key == NULL)
        return BAD_FUNC_ARG;

    key->type = RSA_PUBLIC;

    if (mp_init(&key->n) != MP_OKAY)
        return MP_INIT_E;

    if (mp_read_unsigned_bin(&key->n, n, nSz) != 0) {
        mp_clear(&key->n);
        return ASN_GETINT_E;
    }

    if (mp_init(&key->e) != MP_OKAY) {
        mp_clear(&key->n);
        return MP_INIT_E;
    }

    if (mp_read_unsigned_bin(&key->e, e, eSz) != 0) {
        mp_clear(&key->n);
        mp_clear(&key->e);
        return ASN_GETINT_E;
    }
    return 0;
}

int my_RSAPSS() {
    RsaKey pubkey;
    WC_RNG rng;
    int ret = 0;
    byte* plain;
    //public key
    byte n[] = { 0xb7,0xe9,0x74,0x4b,0x45,0xfa,0xa6,0x20,0xd3,0x1c,0x30,0xe9,0x63,0x86,0xe9,0xcd,0x5f,0xb9,0x93,0xde,0xca,0x45,0xc9,0xd6,0x08,0x94,0xf7,0x7d,0xb9,0xee,0xa9,0xd0,0x78,0x45,0x76,0x94,0x80,0x9d,0xf7,0x05,0x24,0xd7,0x30,0xe2,0xc0,0x0f,0x04,0x6e,0x60,0x53,0x23,0xbd,0x50,0x03,0xbf,0x2c,0xa9,0xbb,0xb4,0x5c,0xc5,0x11,0x5a,0x1d,0xce,0x25,0x7d,0x42,0x03,0x4f,0x7e,0x1c,0x7a,0x3e,0x1a,0x68,0xe8,0x9a,0x00,0x10,0x8d,0x18,0x28,0xac,0x26,0xbd,0x71,0xae,0x4a,0xc9,0xb9,0x23,0x0b,0x9b,0xc1,0x01,0x67,0x46,0xa9,0x01,0x5e,0x70,0xf1,0xd9,0xbd,0x7f,0x56,0x4b,0x97,0x61,0x64,0xff,0xc1,0xd9,0x6e,0x93,0xab,0x40,0x66,0xd5,0xcb,0xf4,0x02,0xf5,0xfc,0x53,0x11,0x51,0xa9,0x80,0x5c,0x07,0x16,0xab,0xcb,0x98,0x25,0xfe,0x02,0xf3,0x89,0x7e,0x57,0x91,0x7a,0x64,0xcc,0x2c,0x7a,0x71,0xe8,0x83,0x33,0x59,0x0a,0xa9,0x59,0x23,0xcf,0x4a,0x6b,0xe4,0x24,0x1a,0xf7,0x8c,0xa9,0x04,0x5d,0x65,0xb6,0x74,0x87,0x19,0x42,0x49,0xe3,0x69,0x03,0xdd,0xa4,0xc9,0x75,0xfe,0xa7,0x3c,0x07,0xc1,0x91,0x67,0x54,0x45,0xfe,0x5f,0xcf,0x45,0x72,0xf8,0xbd,0x47,0x95,0xba,0x81,0xa7,0x54,0x50,0x55,0x29,0x92,0x2f,0x81,0x82,0x71,0x9b,0x43,0x1c,0xeb,0x27,0x16,0xca,0x87,0xe2,0xba,0x83,0xa0,0x1e,0x85,0xef,0x75,0xe4,0x63,0x88,0x2d,0x0b,0x53,0x76,0xb6,0xb3,0xd6,0x68,0x19,0xe2,0x6c,0x2b,0x67,0x4f,0x0a,0x9d,0xde,0xfe,0x93,0x42,0x43,0xce,0x87,0xad };
    byte e[] = { 0x01,0x00,0x01};

    /*start init key*/
    XMEMSET(&pubkey, 0, sizeof(pubkey));
    XMEMSET(&rng, 0, sizeof(rng));

    wc_InitRsaKey(&pubkey, NULL);	                                                // init pubkey area
    wc_InitRng(&rng);				                                                // get random number to rng
    ret = wc_RsaPublicKeyDecodeRaw(n, sizeof(n), e, sizeof(e), &pubkey);            // increase publickey to pubkey
    ret = wc_RsaSetRNG(&pubkey, &rng);                                              //increase rng to pubkey
/*end init key*/

    byte digest[WC_SHA256_DIGEST_SIZE];
    byte inStr[] = { 0xFE,0xBE,0xAC,0x00,0x00,0x00,0x00,0x2C,0x00,0x00,0x00,0x01,0xFE,0xBD,0x00,0x20,0x00,0x01,0xAB,0xE0,0x94,0xC6,0x48,0xC9,0xCE,0x21,0x0C,0xE0,0x88,0xA4,0x6F,0x1A,0x8B,0xFA,0x78,0x3F,0x21,0xB1,0xEB,0x91,0x8F,0x48,0xCF,0x79,0x09,0x78,0xD9,0x04,0x9C,0x00,0x34,0x40 };
    byte result[] = { 0x6B,0xC4,0x27,0xC2,0x77,0x84,0xD2,0x62,0xA8,0x2B,0xA6,0x4B,0xD5,0xF3,0x9C,0x66,0x00,0x72,0xA1,0xB9,0x36,0x0D,0x3F,0x2D,0x30,0x7D,0x83,0x3B,0xE4,0x5B,0x3D,0xB9,0x3D,0x90,0x52,0xFF,0x14,0xC7,0x60,0xD9,0x54,0xCA,0xED,0x39,0x70,0x1A,0x82,0x80,0xB2,0xD4,0x3A,0xF5,0x83,0x9A,0x91,0xC1,0x17,0x82,0xF6,0x78,0x3C,0x5A,0x75,0x01,0x4F,0xF0,0x46,0xEA,0x37,0xFE,0xC5,0x20,0x0D,0xFC,0xF5,0x4E,0xD6,0x4D,0xA1,0x19,0x92,0x6E,0x1C,0xF9,0x39,0x16,0xE2,0x43,0x1C,0x84,0x84,0x64,0x85,0x1E,0x84,0x02,0x51,0x99,0xB7,0x9B,0xB3,0x58,0x75,0xA1,0xE5,0xE5,0xBB,0x27,0x08,0xEB,0x8F,0xC4,0xBC,0xCF,0x6E,0x1E,0xB8,0xA3,0x62,0x7B,0xDE,0x2F,0xD7,0xDE,0xEC,0xAF,0x3C,0x8E,0xCF,0x24,0x27,0x62,0x68,0x50,0x5B,0x05,0x99,0x43,0x0E,0x2A,0x45,0xD6,0x2A,0x96,0xD5,0x31,0xE8,0xDB,0xD9,0xB1,0x30,0x29,0x6C,0x92,0xD9,0x53,0xAC,0x8D,0x22,0x32,0x49,0x55,0x68,0x4D,0x88,0xB4,0xA6,0xD1,0xD6,0xEF,0xAC,0x43,0x06,0x3F,0xD2,0x98,0x97,0x22,0xBD,0x7E,0x63,0xBB,0xCA,0x2D,0x12,0x2A,0x9A,0x33,0x58,0x9A,0x47,0x3F,0x1D,0x0F,0x0E,0xD2,0x58,0xA8,0x8F,0xE5,0xAF,0x6D,0xF4,0xDE,0x48,0x58,0x0E,0x66,0x67,0x48,0x33,0x7A,0x9D,0x2B,0x0C,0xCC,0xA1,0xB3,0xF2,0x12,0x35,0xB3,0x1D,0x0C,0x14,0xB7,0xA5,0xBB,0xE0,0x7C,0x04,0x45,0x9A,0x33,0x1B,0x27,0x53,0x10,0xA2,0x96,0xCD,0xE8,0x91,0xE3,0x2B,0x7E,0x8A,0xE5,0xBC,0x33,0xD3,0x95,0xDA,0x63,0xB4,0xFC };
    word32 inLen = sizeof(inStr);
    word32 resultLen = sizeof(result);
    word32 digestSz;
    word32 plainSz;

    DECLARE_VAR_INIT(in, byte, inLen, inStr, HEAP_HINT);

    ret = wc_Hash(WC_HASH_TYPE_SHA256, in, inLen, digest, sizeof(digest));
    digestSz = wc_HashGetDigestSize(WC_HASH_TYPE_SHA256);

    plain = NULL;

    plainSz = wc_RsaPSS_VerifyInline_ex(result, resultLen, &plain, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, -1, &pubkey);
    //    plainSz = ret;
    ret = wc_RsaPSS_CheckPadding_ex(digest, digestSz, plain, plainSz, WC_HASH_TYPE_SHA256, -1, wc_RsaEncryptSize(&pubkey) * 8);

    printf("PSS verify code is %d\n", ret);
    return ret;
}

int testsuite_test(int argc, char** argv){
    printf("start RSA-PSS\n");
    my_RSAPSS();
    printf("RSA  test finished!\n");
    return 0;
}

int main(int argc, char** argv){
    return testsuite_test(argc, argv);
}